package sip

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"gitee.com/slh1992/plugin-sip/utils"
	"golang.org/x/net/html/charset"
)

type PTZ_Cmd_type int

const (
	Ptz_ctrl_halt      PTZ_Cmd_type = iota //停止0
	Ptz_ctrl_right                         //右转1
	Ptz_ctrl_rightup                       //右上2
	Ptz_ctrl_up                            //向上3
	Ptz_ctrl_leftup                        //左上4
	Ptz_ctrl_left                          //向左5
	Ptz_ctrl_leftdown                      //左下6
	Ptz_ctrl_down                          //向下7
	Ptz_ctrl_rightdown                     //右下8
	Ptz_ctrl_zoom                          //镜头放大/缩小9
	Ptz_ctrl_iris                          //光圈放大/缩小10
	Ptz_ctrl_focus                         //镜头聚焦/放焦11
)

func CreatePtzCmd(ptzType PTZ_Cmd_type, param int) string {
	bytes := make([]byte, 8)
	bytes[0] = 0xA5
	bytes[1] = 0x0F
	bytes[2] = 0x01
	bytes[3] = 0x00
	bytes[4] = 0x00
	bytes[5] = 0x00
	bytes[6] = 0x00
	bytes[7] = 0x00
	cmdType := PTZ_Cmd_type(0)
	if param != 0 {
		cmdType = ptzType
	}
	paramVal := uint8(param)
	switch cmdType {
	case Ptz_ctrl_halt:
		if ptzType == Ptz_ctrl_focus || ptzType == Ptz_ctrl_iris {
			bytes[3] = 0x40
		}
		break
	case Ptz_ctrl_right:
		bytes[3] = 0x01
		bytes[4] = paramVal & 0xFF
		break
	case Ptz_ctrl_rightup:
		bytes[3] = 0x09
		bytes[4] = paramVal & 0xFF
		bytes[5] = paramVal & 0xFF
		break
	case Ptz_ctrl_up:
		bytes[3] = 0x08
		bytes[4] = paramVal & 0xFF
		break
	case Ptz_ctrl_leftup:
		bytes[3] = 0x0A
		bytes[4] = paramVal & 0xFF
		bytes[5] = paramVal & 0xFF
		break
	case Ptz_ctrl_left:
		bytes[3] = 0x02
		bytes[4] = paramVal & 0xFF
		break
	case Ptz_ctrl_leftdown:
		bytes[3] = 0x06
		bytes[4] = paramVal & 0xFF
		bytes[5] = paramVal & 0xFF
		break
	case Ptz_ctrl_down:
		bytes[3] = 0x04
		bytes[4] = paramVal & 0xFF
		break
	case Ptz_ctrl_rightdown:
		bytes[3] = 0x05
		bytes[4] = paramVal & 0xFF
		bytes[5] = paramVal & 0xFF
		break
	case Ptz_ctrl_zoom:
		if param > 0 {
			bytes[3] = 0x10
			bytes[6] = (paramVal & 0x0F) << 4
		} else if param < 0 {
			bytes[3] = 0x20
			bytes[6] = ((-paramVal) & 0x0F) << 4
		}
		break
	case Ptz_ctrl_iris:
		if param > 0 {
			bytes[3] = 0x44
			bytes[5] = paramVal & 0xFF
		} else if param < 0 {
			bytes[3] = 0x48
			bytes[5] = (-paramVal) & 0xFF
		}
		break
	case Ptz_ctrl_focus:
		if param > 0 {
			bytes[3] = 0x41
			bytes[4] = paramVal & 0xFF
		} else if param < 0 {
			bytes[3] = 0x42
			bytes[4] = (-paramVal) & 0xFF
		}
		break
	default:
		break
	}
	var check int
	var result string
	for i := 0; i < 7; i++ {
		check += int((bytes[i]))
		result += fmt.Sprintf("%02x", bytes[i])
	}
	bytes[7] = uint8(check % 256)
	result += fmt.Sprintf("%02x", bytes[7])
	return result
}

type PtzCmdBody struct {
	XMLName  xml.Name `xml:"Control"`
	CmdType  string
	DeviceID string
	SN       string
	PTZCmd   string
}

func (c *PtzCmdBody) String() string {
	xmlStr, err := XmlMashal(c)
	if err != nil {
		return ""
	}
	return xmlStr
}

func (c *PtzCmdBody) Decode(data string) error {
	decoder := xml.NewDecoder(bytes.NewReader([]byte(data)))
	decoder.CharsetReader = charset.NewReaderLabel
	err := decoder.Decode(c)
	if err != nil {
		err = utils.DecodeGbk(c, []byte(data))
		if err != nil {
			return err
		}
	}
	return nil
}
